package com.bear.newsset.adapter;

import android.annotation.SuppressLint;
import androidx.annotation.DrawableRes;
import androidx.annotation.MenuRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.widget.PopupMenu;

import com.bear.newsset.R;
import com.bumptech.glide.RequestManager;
import com.jcodecraeer.xrecyclerview.XRecyclerView;

import java.util.List;

/**
 * XRecyclerView基本适配器
 */
public abstract class BaseXRecyclerViewAdapter<E extends BaseXRecyclerViewAdapter.BaseXrvEntity>
        extends XRecyclerView.Adapter<BaseViewHolder>
        implements TouchStyle, ItemMenu<E> {
    /**
     * 子项按下事件接口
     */
    public interface OnItemDownListener<E extends BaseXrvEntity> {
        void onItemDown(View view, E itemData, int position);
    }

    /**
     * 子项点击事件接口
     */
    public interface OnItemClickListener<E extends BaseXrvEntity> {
        void onItemClick(View view, E itemData, int position);
    }

    /**
     * 子项菜单点击事件接口
     * @param <E>
     */
    public interface OnItemMenuClickListener<E extends BaseXrvEntity> {
        void onItemMenuClick(View view, MenuItem menuItem, E itemData, int position);
    }

    @DrawableRes
    private int upRes = R.drawable.item_down;
    @DrawableRes
    private int downRes = R.drawable.item_up;
    @MenuRes
    private int clickMenuRes, longClickMenuRes;

    //数据源
    private List<E> mDataList;
    private boolean isTouchStyleEnable = true;  //默认启用触摸样式
    private int mCurrentPosition = 0;           //当前选中的位置（按下时）
    private PopupMenu mPopupMenu;
    private RequestManager mGlide;

    private BaseViewHolder.OnTouchListener mViewTouchListener;
    private OnItemDownListener<E> mOnItemDownListener;
    private OnItemClickListener<E> mOnItemClickListener;
    private OnItemClickListener<E> mOnItemLongClickListener;
    private OnItemMenuClickListener<E> mOnItemMenuClickListener;
    private OnItemMenuClickListener<E> mOnItemMenuLongClickListener;

    public BaseXRecyclerViewAdapter(@NonNull List<E> mDataList) {
        this.mDataList = mDataList;
    }

    public BaseXRecyclerViewAdapter(@Nullable RequestManager mGlide, @NonNull List<E> mDataList) {
        this.mGlide = mGlide;
        this.mDataList = mDataList;
    }

    @NonNull
    public RequestManager getGlide() {
        if( mGlide == null ) throw new NullPointerException("RequestManager can't be null!");
        return mGlide;
    }

    /**
     * 子项按下事件监听器
     * @param listener              listener
     * @return                      返回当前类
     */
    public BaseXRecyclerViewAdapter setOnDownListener(OnItemDownListener<E> listener,
                                                       @MenuRes int menuRes) {
        mOnItemDownListener = listener;
        return this;
    }
    public OnItemDownListener getOnItemDownListener() {
        return mOnItemDownListener;
    }

    /**
     * 子项点击事件监听器
     * @param listener              listener
     * @return                      返回当前类
     */
    public BaseXRecyclerViewAdapter setOnItemClickListener(OnItemClickListener<E> listener) {
        mOnItemClickListener = listener;
        return this;
    }
    public OnItemClickListener getOnItemClickListener() {
        return mOnItemClickListener;
    }

    /**
     * 子项长按事件监听器
     * @param listener              listener
     * @return                      返回当前类
     */
    public BaseXRecyclerViewAdapter setOnItemLongListener(OnItemClickListener<E> listener) {
        mOnItemLongClickListener = listener;
        return this;
    }
    public OnItemClickListener<E> getOnItemLongListener() {
        return mOnItemLongClickListener;
    }

    /**
     * 子项带菜单点击事件监听器
     * @param listener              listener
     * @return                      返回当前类
     */
    public BaseXRecyclerViewAdapter setOnItemMenuClickListener(OnItemMenuClickListener<E> listener,
                                                               @MenuRes int menuRes) {
        clickMenuRes = menuRes;
        mOnItemMenuClickListener = listener;
        return this;
    }
    public OnItemMenuClickListener<E> getOnItemMenuClickListener() {
        return mOnItemMenuClickListener;
    }

    /**
     * 子项带菜单长按事件监听器
     * @param listener              listener
     * @return                      返回当前类
     */
    public BaseXRecyclerViewAdapter setOnItemMenuLongListener(OnItemMenuClickListener<E> listener,
                                                              @MenuRes int menuRes) {
        longClickMenuRes = menuRes;
        mOnItemMenuLongClickListener = listener;
        return this;
    }
    public OnItemMenuClickListener getOnItemMenuLongClickListener() {
        return mOnItemMenuLongClickListener;
    }

    /**
     * 是否启用/禁用点击的样式
     * @param isEnable  是否启用
     * @return          返回当前类
     */
    public BaseXRecyclerViewAdapter setTouchStyleEnable(boolean isEnable) {
        isTouchStyleEnable = isEnable;
        return this;
    }

    @Override
    public int getItemCount() {
        return mDataList.size();
    }

    public List<E> getDataList() {
        return mDataList;
    }

    /**
     * 绑定ViewHolder
     * @param viewHolder    viewHolder
     * @param position      position
     */
    @SuppressLint({"RecyclerView", "ClickableViewAccessibility"})
    @Override
    public void onBindViewHolder(@NonNull final BaseViewHolder viewHolder, int position) {
        View itemView = viewHolder.itemView;
        //Item点击事件监听器
        viewHolder.setOnClickListener(v -> doClick(v, true));
        //Item长按事件监听器
        viewHolder.setOnLongClickListener(v -> {
            doClick(v, false);
            return false;
        });
        //ItemTouch事件监听器
        viewHolder.setOnTouchListener((BaseViewHolder.OnTouchListener) (v, ev) -> {
            mCurrentPosition = position;
            //ItemView的触摸事件
            onItemTouchStyle( itemView, ev );
            //回调Touch事件
            if( mViewTouchListener != null ) mViewTouchListener.onTouch(v, ev);
            return true;
        });
    }

    /**
     * 监听item的onTouch事件，因为自身已实现该方法
     * @param listener      监听器
     */
    public void setOnItemTouchListener(BaseViewHolder.OnTouchListener listener) {
        mViewTouchListener = listener;
    }

    /**
     * 处理点击事件
     * @param v             view
     * @param isClick       true：点击，false：长按
     */
    private void doClick(View v, boolean isClick) {
        E itemData = getCurrentItemData();
        if( isClick ) {
            if( mOnItemClickListener != null ) {
                mOnItemClickListener.onItemClick(v, itemData, mCurrentPosition);
            }
        }else {
            if( mOnItemLongClickListener != null ) {
                mOnItemLongClickListener.onItemClick(v, itemData, mCurrentPosition);
            }
        }
        //按下事件监听器
        if( mOnItemDownListener != null ) {
            mOnItemDownListener.onItemDown(v, itemData, mCurrentPosition);
        }

        //设置显示菜单
        setShowMenu(v, itemData, mCurrentPosition, isClick ? clickMenuRes : longClickMenuRes);
    }

    /**
     * 设置触摸样式
     * @param v  View
     */
    @SuppressLint("ClickableViewAccessibility")
    public void onItemTouchStyle(@NonNull View v, MotionEvent ev) {
        if( !isTouchStyleEnable ) return;
        /* 设置触摸样式 */
        if( setUpResources() > 0 ) upRes = setUpResources();
        if( setDownResources() > 0 ) downRes = setDownResources();
        v.setBackgroundResource(upRes);

        /* 监听按下和弹起更改item背景颜色 */
        int action = ev.getAction();
        if( action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_MOVE ) {
            //按下
            v.setBackgroundResource(downRes);
        }else if( action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL ) {
            //弹起
            v.setBackgroundResource(upRes);
        }
    }

    /**
     * 显示菜单
     * @param view      需要在指定view上显示
     */
    public void setShowMenu(final View view,
                            final E itemData, final int position, @MenuRes int menuRes) {
        if( menuRes == 0 ) { return; }
        //获取弹出菜单
        PopupMenu menu = getPopupMenu( view );
        menu.getMenuInflater().inflate(menuRes, menu.getMenu());
        //设置属性
        setMenuAttr(menu, itemData);
        //菜单点击事件监听器
        menu.setOnMenuItemClickListener(item -> {
            OnItemMenuClickListener<E> clicklistener = getOnItemMenuClickListener();
            OnItemMenuClickListener<E> longListener = getOnItemMenuLongClickListener();
            if( clicklistener != null ) {
                clicklistener.onItemMenuClick(view, item, itemData, position);
            }
            if( longListener != null ) {
                longListener.onItemMenuClick(view, item, itemData, position);
            }
            return false;
        });
        menu.show();
    }

    /**
     * 设置菜单属性
     * @param menu          菜单
     * @param itemData      item数据
     */
    @Override
    public void setMenuAttr(PopupMenu menu, E itemData) {
        //默认不做任何操作
    }

    /**
     * 获取弹出菜单
     * @param v                 需要弹出菜单的View
     * @param isMultipleExist   允许多个菜单存在
     * @return                  菜单
     */
    public PopupMenu getPopupMenu(View v, boolean isMultipleExist) {
        if( !isMultipleExist && mPopupMenu != null ) {
            mPopupMenu.dismiss();
            mPopupMenu.getMenu().clear();
            mPopupMenu.getMenu().close();
        }
        mPopupMenu = new PopupMenu(v.getContext(), v);
        return mPopupMenu;
    }

    public PopupMenu getPopupMenu(View v) {
        return getPopupMenu(v, false);
    }

    /**
     * 获取当前Item数据（选中时）
     * @return      ItemData
     */
    public E getCurrentItemData() {
        return mDataList.get( mCurrentPosition );
    }

    /**
     * 获取当前Item位置（选中时）
     * @return      位置
     */
    public int getCurrentPosition() {
        return mCurrentPosition;
    }

    public interface BaseXrvEntity { }
}

/*
 * 点击样式接口
 */
interface TouchStyle {
    int setUpResources();       //抬起时
    int setDownResources();     //按下时
}

interface ItemMenu<E extends BaseXRecyclerViewAdapter.BaseXrvEntity> {
    void setMenuAttr(PopupMenu menu, E itemData);
}